import BaseProvider from './base';

class InternalUploadProvider extends BaseProvider {
  constructor(options = {}) {
    super();
    this.provider = 'qiniu';
    this.domain = options.domain || 'cdn.isscloud.site'; // 默认域名
    this.uploadPath = options.uploadPath || 'uni-media-library'; // 基础存储路径
    this.compressQuality = options.compressQuality || 80; // 压缩质量 (0-100)
    this.compressWidth = options.compressWidth || 1920; // 压缩后最大宽度
    this.compressHeight = options.compressHeight || 1920; // 压缩后最大高度
  }

  // Helper method to compress image
  async compressImage(filePath) {
    // 判断运行环境
    if (process.env.UNI_PLATFORM === 'h5') {
      // H5环境使用Canvas压缩
      try {
        return await this.compressViaCanvas(filePath);
      } catch (compressErr) {
        console.warn('Canvas压缩失败，使用原图上传', compressErr);
        return filePath.replace(/\.[^/.]+$/, '') + '.webp';
      }
    } else if (uni.compressImage && typeof uni.compressImage === 'function') {
      // 小程序/App环境使用uni.compressImage
      try {
        const compressedResult = await new Promise((resolve, reject) => {
          uni.compressImage({
            src: filePath,
            quality: this.compressQuality,
            width: this.compressWidth,
            height: this.compressHeight,
            format: 'webp',
            success: resolve,
            fail: reject
          });
        });
        return compressedResult.tempFilePath;
      } catch (compressErr) {
        console.warn('图片压缩失败，使用原图上传', compressErr);
        return filePath.replace(/\.[^/.]+$/, '') + '.webp';
      }
    } else {
      console.warn('当前环境不支持压缩，使用原图上传');
      return filePath.replace(/\.[^/.]+$/, '') + '.webp';
    }
  }

  // H5环境专用的Canvas压缩方法
  async compressViaCanvas(filePath) {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.crossOrigin = 'Anonymous';
      img.src = filePath;

      img.onload = () => {
        try {
          const canvas = document.createElement('canvas');
          const ctx = canvas.getContext('2d');

          // 计算压缩后的尺寸（保持宽高比）
          let width = img.width;
          let height = img.height;

          if (width > this.compressWidth || height > this.compressHeight) {
            const ratio = Math.min(this.compressWidth / width, this.compressHeight / height);
            width = width * ratio;
            height = height * ratio;
          }

          canvas.width = width;
          canvas.height = height;
          ctx.drawImage(img, 0, 0, width, height);

          // 转换为WebP格式
          canvas.toBlob((blob) => {
            const compressedUrl = URL.createObjectURL(blob);
            resolve(compressedUrl);
          }, 'image/webp', this.compressQuality / 100);
        } catch (err) {
          reject(err);
        }
      };

      img.onerror = (err) => {
        reject(new Error('图片加载失败'));
      };
    });
  }

  async upload(files) {
    // 上传每张新图片
    for (let i = 0; i < files.length; i++) {
      const file = files[i];

      try {
        // 准备云存储路径
        const date = new Date();
        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        const day = date.getDate();
        const cloudPath = `${this.uploadPath}/${year}/${month}/${day}/${Date.now()}_${Math.random().toString().slice(2, 7)}.webp`;

        // 压缩图片
        file.setStatus('compressing');
        this.emit('progress', file);

        const compressedFilePath = await this.compressImage(file.originUrl);

        // 使用扩展存储云对象上传
        const uniCloudStorageExtCo = uniCloud.importObject("ext-storage-co");
        const uploadFileOptionsRes = await uniCloudStorageExtCo.getUploadFileOptions({
          cloudPath: cloudPath,
          domain: this.domain, // 使用配置的域名
        });

        // 执行上传
        const uploadResult = await uni.uploadFile({
          ...uploadFileOptionsRes.uploadFileOptions,
          filePath: compressedFilePath,
          onUploadProgress: (progressEvent) => {
            file.setStatus('uploading');
            file.setPercent(Math.floor((progressEvent.loaded / progressEvent.total) * 100));
            this.emit('progress', file);
          }
        });

        const obj = JSON.parse(uploadResult.data);
        const fileID = `qiniu://${obj.key}`;
        file.setStatus('uploaded');
        file.setUrl(fileID);
        file.setPercent(100);

        // Clean up compressed temp file if it's different from original
        if (compressedFilePath !== file.originUrl && uni.removeSavedFile && typeof uni.removeSavedFile === 'function') {
          try {
            await uni.removeSavedFile({
              filePath: compressedFilePath
            });
          } catch (cleanError) {
            console.warn('Failed to clean temp file:', cleanError);
          }
        }
      } catch (error) {
        file.setStatus('failed');
        file.setError(error);
        this.emit('error', file);
        continue; // Continue with next file even if one fails
      }

      if ((i + 1) === files.length) {
        this.emit('success', files);
      }
    }
  }

  async cloudUpload(files, options) {
    const { imageLibraryProvider } = options;
    for (let i = 0; i < files.length; i++) {
      const file = files[i];

      try {
        file.setStatus('compressing');
        this.emit('progress', file);

        // Compress image first
        const compressedFilePath = await this.compressImage(file.originUrl);

        file.setStatus('uploading');
        file.setPercent(0);
        this.emit('progress', file);

        const result = await uniMediaLibraryCo.uploadImage({
          url: compressedFilePath,
          id: file.id,
          provider: imageLibraryProvider
        });

        if (!result.data.fileID) {
          file.setStatus('failed');
          file.setError(new Error('上传失败'));
          this.emit('error', file);
          return;
        }

        file.setStatus('uploaded');
        file.setUrl(result.data.fileID);
        file.setPercent(100);
        file.setAttributes(result.data.detail);

        // Clean up compressed temp file if it's different from original
        if (compressedFilePath !== file.originUrl && uni.removeSavedFile && typeof uni.removeSavedFile === 'function') {
          try {
            await uni.removeSavedFile({
              filePath: compressedFilePath
            });
          } catch (cleanError) {
            console.warn('Failed to clean temp file:', cleanError);
          }
        }
      } catch (e) {
        file.setStatus('failed');
        file.setError(e);
        console.error(e);
        this.emit('error', file);
      }

      if ((i + 1) === files.length) {
        this.emit('success', files);
      }
    }
  }
}

export default InternalUploadProvider;